import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:website.core/core/application/blocs/app_navigator_bloc/bloc.dart';
import 'package:website.core/core/application/blocs/auth_bloc/bloc.dart';
import 'package:website.core/core/application/blocs/url_launcher_bloc/bloc.dart';
import 'package:website.core/core/domain/clients/api_client.dart';
import 'package:website.core/core/domain/helpers/add_spaces_to_price/add_spaces_to_price.dart';
import 'package:website.core/core/domain/helpers/prettify_web_purchase_item_prices/prettify_web_purchase_item_prices.dart';
import 'package:website.core/core/domain/helpers/validate_email/validate_email.dart';
import 'package:website.core/core/domain/helpers/validate_password/validate_password.dart';
import 'package:website.core/core/domain/repositories/auth_repository/repository.dart';
import 'package:website.core/core/domain/repositories/purchase_item_repository/repository.dart';
import 'package:website.core/core/domain/repositories/purchased_item_repository/repository.dart';
import 'package:website.core/core/domain/repositories/user_local_repository/repository.dart';
import 'package:website.core/core/domain/repositories/user_remote_repository/repository.dart';
import 'package:website.core/core/domain/repositories/web_payment_method_repository/repository.dart';
import 'package:website.core/core/domain/repositories/web_transaction_history_repository/repository.dart';
import 'package:website.core/core/domain/stores/user_store.dart';
import 'package:website.core/core/domain/use_cases/obtain_authentication_data/use_case.dart';
import 'package:website.core/core/domain/use_cases/sign_out/use_case.dart';
import 'package:website.core/core/domain/use_cases/update_access_credentials/use_case.dart';
import 'package:website.core/core/infrastructure/clients/api_client.dart';
import 'package:website.core/core/infrastructure/repositories/auth_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/purchase_item_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/purchased_item_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/user_local_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/user_remote_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/web_payment_method_repository/repository.dart';
import 'package:website.core/core/infrastructure/repositories/web_transaction_history_repository/repository.dart';
import 'package:website.core/core/infrastructure/stores/user_store.dart';

final sl = GetIt.asNewInstance();

Future<void> init() async {
  // use cases

  sl.registerLazySingleton<ObtainAuthenticationData>(() {
    return ObtainAuthenticationDataImpl(
      userLocalRepository: sl(),
    );
  });

  sl.registerLazySingleton<SignOut>(() {
    return SignOutImpl(
      authRepository: sl(),
      userLocalRepository: sl(),
    );
  });

  sl.registerLazySingleton<UpdateAccessCredentials>(() {
    return UpdateAccessCredentialsImpl(
      apiClient: sl(),
      userLocalRepository: sl(),
    );
  });

  // domain helpers

  sl.registerLazySingleton<ValidateEmail>(() {
    return const ValidateEmailImpl();
  });

  sl.registerLazySingleton<ValidatePassword>(() {
    return const ValidatePasswordImpl();
  });

  sl.registerLazySingleton<PrettifyWebPurchaseItemPrices>(() {
    return PrettifyWebPurchaseItemPricesImpl(
      addSpacesToPrice: sl(),
    );
  });

  sl.registerLazySingleton<AddSpacesToPrice>(() {
    return const AddSpacesToPriceImpl();
  });

  // clients

  sl.registerLazySingleton<ApiClient>(() {
    return createApiClient(
      baseClient: http.Client(),
    );
  });

  // stores

  sl.registerLazySingleton<UserStore>(() {
    return const UserStoreImpl();
  });

  // repositories

  sl.registerLazySingleton<AuthRepository>(() {
    return AuthRepositoryImpl(
      httpClient: http.Client(),
      apiClient: sl(),
    );
  });

  sl.registerLazySingleton<PurchaseItemRepository>(() {
    return PurchaseItemRepositoryImpl(
      httpClient: http.Client(),
    );
  });

  sl.registerLazySingleton<PurchasedItemRepository>(() {
    return PurchasedItemRepositoryImpl(
      apiClient: sl(),
    );
  });

  sl.registerLazySingleton<UserLocalRepository>(() {
    return UserLocalRepositoryImpl(
      store: sl(),
    );
  });

  sl.registerLazySingleton<UserRemoteRepository>(() {
    return UserRemoteRepositoryImpl(
      httpClient: http.Client(),
      apiClient: sl(),
    );
  });

  sl.registerLazySingleton<WebPaymentMethodRepository>(() {
    return WebPaymentMethodRepositoryImpl(
      apiClient: sl(),
    );
  });

  sl.registerLazySingleton<WebTransactionHistoryItemRepository>(() {
    return WebTransactionHistoryItemRepositoryImpl(
      apiClient: sl(),
    );
  });
}

// auth

void registerAuthBloc() {
  sl.registerLazySingleton(() {
    return AuthBloc(
      apiClient: sl(),
      obtainAuthenticationData: sl(),
      updateAccessCredentials: sl(),
    );
  });
}

void unregisterAuthBloc() {
  sl.unregister<AuthBloc>(
    disposingFunction: (authBloc) {
      authBloc.close();
    },
  );
}

// navigator

void registerAppNavigatorBloc() {
  sl.registerLazySingleton(() {
    return AppNavigatorBloc(
      authBloc: sl(),
    );
  });
}

void unregisterAppNavigatorBloc() {
  sl.unregister<AppNavigatorBloc>(
    disposingFunction: (appNavigatorBloc) {
      appNavigatorBloc.close();
    },
  );
}

// url launcher

void registerUrlLauncherBloc() {
  sl.registerLazySingleton(() {
    return UrlLauncherBloc();
  });
}

void unregisterUrlLauncherBloc() {
  sl.unregister<UrlLauncherBloc>(
    disposingFunction: (urlLauncherBloc) {
      urlLauncherBloc.close();
    },
  );
}
